//---------------------------------------------------------------------------------
// Copyright (c) 2011, Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------------

namespace Microsoft.ServiceBus.Samples.SimpleSilverlightSample
{
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Browser;
    using System.Windows;
    using System.Windows.Controls;

    public partial class MainPage : UserControl
    {
        private string serviceNamespace;
        private string issuerName;
        private string issuerSecret;

        private string accessToken;

        private string queueName;
        private string createdQueueEntity;

        private string messageBody;
        private string receivedMessage;

        public MainPage()
        {
            InitializeComponent();

            VisualStateManager.GoToState(this, "Step1", false);
        }

        #region Step 1 - Get Token from ACS

        private void GetTokenButtonClicked(object sender, System.Windows.RoutedEventArgs e)
        {
            // Copy parameters from the UI thread - we'll need to access them when
            // running in the background.
            this.serviceNamespace = ServiceNamespace.Text;
            this.issuerName = "owner";
            this.issuerSecret = IssuerSecret.Text;

            var acsEndpoint = "https://" + this.serviceNamespace + "-sb.accesscontrol.windows.net/WRAPv0.9/";

            // Create a request to the Access Control Service WRAP (v0.9) endpoint
            HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(acsEndpoint));
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";

            // Asynchronously acquire the request stream - we need to post values in the request
            // body
            request.BeginGetRequestStream(this.GetToken_GetRequestStreamCompleted, request);
        }

        private void GetToken_GetRequestStreamCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            Stream requestStream = request.EndGetRequestStream(result);

            // Note that the realm used when requesting a token uses the HTTP scheme, even though
            // calls to the service are always issued over HTTPS
            var realm = "http://" + this.serviceNamespace + ".servicebus.windows.net";

            // Prepare the body of the token request
            var postData = "wrap_name=" + Uri.EscapeDataString(this.issuerName) +
                           "&wrap_password=" + Uri.EscapeDataString(this.issuerSecret) +
                           "&wrap_scope=" + Uri.EscapeDataString(realm);

            // Post the name, password and scope formatted as a HTTP Form
            using (var streamWriter = new StreamWriter(requestStream))
            {
                streamWriter.Write(postData);
                streamWriter.Flush();
            }

            // Asynchronously get the response to the token request
            request.BeginGetResponse(this.GetToken_GetResponseCompleted, request);
        }

        private void GetToken_GetResponseCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            var response = (HttpWebResponse)request.EndGetResponse(result);

            using (var responseStream = response.GetResponseStream())
            {
                using (var responseStreamReader = new StreamReader(responseStream))
                {
                    var responseString = responseStreamReader.ReadToEnd();

                    // The response contains the access token and its expiry time
                    // formatted as an HTTP Form like:
                    // wrap_access_token=token&wrap_expiry_time=2000
                    var responseProperties = responseString.Split('&');
                    var tokenProperty = responseProperties[0].Split('=');
                    var token = Uri.UnescapeDataString(tokenProperty[1]);

                    this.accessToken = "WRAP access_token=\"" + token + "\"";
                }
            }

            this.Dispatcher.BeginInvoke(() => VisualStateManager.GoToState(this, "Step2", false));
        }

        #endregion

        #region Step 2 - Create a Queue using the Mangement Service

        private void CreateQueueButtonClicked(object sender, System.Windows.RoutedEventArgs e)
        {
            // Copy parameters from the UI thread - we'll need to access them when
            // running in the background.
            this.queueName = this.NewQueueName.Text;

            // Create the URI of the new Queue, note that this uses the HTTPS scheme
            var queueAddress = "https://" + this.serviceNamespace + ".servicebus.windows.net/" + this.queueName;

            // Create a Put request to create the new queue and add the ACS Authorization Token
            HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(queueAddress));
            request.Method = "PUT";
            request.ContentType = "application/atom+xml";
            request.Headers["Authorization"] = this.accessToken;

            // Asynchronously acquire the request stream - we need to put a request body
            request.BeginGetRequestStream(this.CreateQueue_GetRequestStreamCompleted, request);
        }

        private void CreateQueue_GetRequestStreamCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            Stream requestStream = request.EndGetRequestStream(result);

            // Prepare the body of the create queue request
            var putData = @"<entry xmlns=""http://www.w3.org/2005/Atom"">
                              <title type=""text"">" + this.queueName + @"</title>
                              <content type=""application/xml"">
                                <QueueDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"" />
                              </content>
                            </entry>";

            // Put an Atom Entry at the Queue Uri containing a QueueDescription
            using (var streamWriter = new StreamWriter(requestStream))
            {
                streamWriter.Write(putData);
                streamWriter.Flush();
            }

            // Asynchronously get the response to the create queue request
            request.BeginGetResponse(this.CreateQueue_GetResponseCompleted, request);
        }

        private void CreateQueue_GetResponseCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            var response = (HttpWebResponse)request.EndGetResponse(result);

            using (var responseStream = response.GetResponseStream())
            {
                using (var responseStreamReader = new StreamReader(responseStream))
                {
                    // Read the Atom Entry returned by the service
                    this.createdQueueEntity = responseStreamReader.ReadToEnd();
                }
            }

            this.Dispatcher.BeginInvoke(() => VisualStateManager.GoToState(this, "Step3", false));
        }

        #endregion

        #region Step 3 - Send a Message to the new Queue

        private void SendMessageButtonClicked(object sender, System.Windows.RoutedEventArgs e)
        {
            // Copy parameters from the UI thread - we'll need to access them when running in the background.
            this.messageBody = this.MessageToSend.Text;

            // Create the URI to send the message to
            var messageSendAddress = "https://" + this.serviceNamespace + ".servicebus.windows.net/" + this.queueName + "/Messages";

            // Create a Post request to send a message to the queue and add the ACS Authorization Token
            HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(messageSendAddress));
            request.Method = "POST";
            request.Headers["Authorization"] = this.accessToken;

            // Use the content type to indicate the type of the message body. In this example, the
            // body is plain text.
            request.ContentType = "text/plain";

            // Asynchronously acquire the request stream - we need to post values the message body
            request.BeginGetRequestStream(this.SendMessage_GetRequestStreamCompleted, request);
        }

        private void SendMessage_GetRequestStreamCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            Stream requestStream = request.EndGetRequestStream(result);

            // Post the message body to the stream
            using (var streamWriter = new StreamWriter(requestStream))
            {
                streamWriter.Write(this.messageBody);
                streamWriter.Flush();
            }

            // Asynchronously get the response to the send request
            request.BeginGetResponse(this.SendMessage_GetResponseCompleted, request);
        }

        private void SendMessage_GetResponseCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            var response = (HttpWebResponse)request.EndGetResponse(result);

            // Verify that the response code indicates the message was sent
            if (response.StatusCode != HttpStatusCode.Created)
            {
                throw new Exception("The message was not sent");
            }

            this.Dispatcher.BeginInvoke(() => VisualStateManager.GoToState(this, "Step4", false));
        }

        #endregion

        #region Step 4 - Receive the Message from the Queue

        private void ReceiveMessageButtonClicked(object sender, System.Windows.RoutedEventArgs e)
        {
            // Create the URI to receive the message from (using Receive And Delete semantics)
            var messageReceiveAddress = "https://" + this.serviceNamespace + ".servicebus.windows.net/" + this.queueName + "/Messages/Head?timeout=30";

            // Create a Delete request to remove the first message from the head of the queue
            HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(messageReceiveAddress));
            request.Method = "DELETE";
            request.Headers["Authorization"] = this.accessToken;

            // Asynchronously get the response to the receive request
            request.BeginGetResponse(this.ReceiveMessage_GetResponseCompleted, request);
        }

        private void ReceiveMessage_GetResponseCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            var response = (HttpWebResponse)request.EndGetResponse(result);

            using (var responseStream = response.GetResponseStream())
            {
                using (var responseStreamReader = new StreamReader(responseStream))
                {
                    // Read the message body from the stream
                    this.receivedMessage = responseStreamReader.ReadToEnd();
                }
            }

            this.Dispatcher.BeginInvoke(() =>
            {
                this.ReceivedMessage.Text = this.receivedMessage;
                VisualStateManager.GoToState(this, "Step5", false);
            });
        }

        #endregion

        #region Step 5 - Delete the Queue

        private void DeleteQueueButtonClicked(object sender, System.Windows.RoutedEventArgs e)
        {
            // Create the URI of the queue to delete, note that this uses the HTTPS scheme
            var queueAddress = "https://" + this.serviceNamespace + ".servicebus.windows.net/" + this.queueName;

            // Create a Delete request and add the Auth Token
            HttpWebRequest request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(queueAddress));
            request.Method = "DELETE";
            request.Headers["Authorization"] = this.accessToken;

            // Asynchronously get the response
            request.BeginGetResponse(this.DeleteQueue_GetResponseCompleted, request);
        }

        private void DeleteQueue_GetResponseCompleted(IAsyncResult result)
        {
            // End the Async Call
            var request = (HttpWebRequest)result.AsyncState;
            var response = (HttpWebResponse)request.EndGetResponse(result);

            // Verify that the response code indicates the queue was deleted
            if (response.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("The queue was not deleted");
            }

            this.Dispatcher.BeginInvoke(() => MessageBox.Show("Sample Finished!"));
        }

        #endregion
    }
}
